﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections;
using System.Collections.Generic;

namespace rpncs {
    public class Calc {
        public Queue<Double> calcStack = new Queue<Double>();
        //Decimal d = new Decimal(0);
        private static IList<String> entries = new List<String>();
        public const bool LN = true, LOG = false;
        public const int ADD= 1, 
            MULT = 2, 
            SUB = 3, 
            DIV = 4, 
            SIN=5, 
            COS=6, 
            TAN=7;

        public void clearAll() {
            entries.Clear();
            calcStack.Clear();
        }
        public Double doBasicCalcs( int o ) {

            Double d = calcStack.Dequeue();


            while (calcStack.Count > 0) {
                Double t = calcStack.Dequeue();
                switch (o) {
                    case ADD:
                        d = d + t;

                        break;

                    case SUB:
                        d = d - t;
                        break;
                    case MULT:
                        d = d * t;
                        break;
                    case DIV:
                        if (t.Equals( 0 )) {
                            throw new DivideByZeroException();
                        }
                        d = d / t;
                        break;

                }
            }

            return d;
        }

        public void addToList( int i ) {
            entries.Add( i + "" );
        }

        public void addToList( String str ) {
            entries.Add( str );

        }

        public void addToStack( String str ) {
            calcStack.Enqueue( Convert.ToDouble( str ) );
        }
        public void xPowerY() {

            double x = calcStack.Dequeue();
            double y = calcStack.Dequeue();
            calcStack.Enqueue( Math.Pow( x, y ) );

        }

        public void eToX() {

            double x = calcStack.Dequeue();

            calcStack.Enqueue( Math.Pow( Math.E, x ) );
        }

        public void sqrt() {
            double d = calcStack.Dequeue();
            calcStack.Enqueue( Math.Sqrt( d ) );
        }

        public void logarithm( Boolean isNatural ) {

            double d = calcStack.Dequeue();

            if (isNatural) {
                calcStack.Enqueue( Math.Log( d ) );
            }
            else {

                calcStack.Enqueue( Math.Log10( d ) );
            }

        }

        public void percentage() {
            double x = calcStack.Dequeue();
            double y = calcStack.Dequeue();
            calcStack.Enqueue( (y / x) * 100 );
        }

        public void tenX() {

            calcStack.Enqueue(Math.Pow(10,calcStack.Dequeue()) );
        }

        public void xSquared() {
            calcStack.Enqueue(Math.Pow(calcStack.Dequeue(),2) );
        }

        public void exponent() {
            calcStack.Enqueue(Math.Pow(10,calcStack.Dequeue()) );
        }
        public void oneOverX() {
            calcStack.Enqueue( 1 / calcStack.Dequeue() );
        }
        public  string Exp(  ) {
            double l = calcStack.Dequeue()* 0.43429448190325176D; // x/Math.log(10);
            double e = System.Math.Floor( l );
            double m = System.Math.Pow( 10, l - e );
            string mat = (Convert.ToString( m )).Substring( 0, 6 );
            return mat + " E+" + Convert.ToString( (int)e );
        }
        public void factorial() {
            double s = calcStack.Dequeue();
            
            
            calcStack.Enqueue(Double.Parse( SimpleFactorial.Factorial( Convert.ToInt32(s) ) ) ) ;
         }
        public void trig( int op, bool shifted, bool hyp ) {

            switch (op) {
                case SIN:
                    if (hyp) {
                        calcStack.Enqueue(Math.Sinh(calcStack.Dequeue() ) );
                        return;
                    }
                    if (shifted) {
                        calcStack.Enqueue( Math.Asin( calcStack.Dequeue() ) );
                        return;
                    }
                    calcStack.Enqueue( Math.Sin( calcStack.Dequeue() ) );
                    break;
                case COS:
                    if (hyp) {
                        calcStack.Enqueue(Math.Cosh(calcStack.Dequeue() ) );
                        return;
                    }
                    if (shifted) {
                        calcStack.Enqueue( Math.Acos( calcStack.Dequeue() ) );
                        return;
                    }
                    calcStack.Enqueue( Math.Cos( calcStack.Dequeue() ) );
                    break;
                case TAN:
                     if (hyp) {
                        calcStack.Enqueue(Math.Tanh(calcStack.Dequeue() ) );
                        return;
                    }
                    if (shifted) {
                        calcStack.Enqueue( Math.Atan( calcStack.Dequeue() ) );
                        return;
                    }
                    calcStack.Enqueue( Math.Tan( calcStack.Dequeue() ) );
                    break;
            }
        }

        public class DivideByZeroException : Exception {
            String message = "Divide By Zero.  Can't do that.";
            public DivideByZeroException() {


            }
            public String getMessage() {
                return message;
            }
        }
    }
}
